#! -*- coding: utf-8 -*-

from flask import request, g, current_app
from mongoengine import Q
from werkzeug.utils import MultiDict

from app.models import (Locality, Destination, DestinationInfo, Tag)
from app.utils import (api_ok, api_error, get_objectId, trim, allowed_file)
from app.decorators import validate_form
from app.forms import LocalityInfoForm, DestinationInfoForm
from app.third_party_api import btapi
from app.controllers import (
    get_destination_info, paginate_queryset, upload_image_func
)


@current_app.route('/vacation/admin/locality/list/', methods=['GET'])
def locality_list():
    """
    ### 说明
    获取国家列表

    #### 请求参数
    不需要参数

    #### 返回结果
    {
      "code": 0,
      "data": [
        {
          "cover": "http://photos.breadtrip.com/covers_2015_05_12_40ea19322bc40289bbae4f8259cd3fd5.png?imageView/2/w/960/",
          "id": "5609ff712e809f57ab1e8b15",
          "name": "泰国",
          "published": false
        },
        ....
      ]
    }
    """

    localities = paginate_queryset(request.args, Locality.objects.all())
    items = []
    for locality in localities:
        items.append({
            'name': locality.name,
            'cover': locality.cover,
            'id': str(locality.id),
            'published': locality.published,
        })
    return api_ok(data=items)


@current_app.route('/vacation/admin/locality/info/', methods=['GET'])
def locality_info():
    """
    ### 说明
    获取指定国家的信息

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    locality_id | N | string |

    #### 返回结果
    {
      "code": 0,
      "data": {
        "cover": "http://photos.breadtrip.com/covers_2015_05_12_40ea19322bc40289bbae4f8259cd3fd5.png?imageView/2/w/960/",
        "id": "5609ff712e809f57ab1e8b15",
        "itinerary_covers": "",
        "latitude": 13.45,
        "longitude": 100.31,
        "name": "泰国",
        "name_en": "Thailand",
        "time_zone": 7
      }
    }
    """

    getter = request.args.get

    item = {}

    locality_id = get_objectId(getter('locality_id'))
    if locality_id:
        locality = Locality.objects.filter(id=locality_id).first()
        if locality:
            location = locality.location
            if location:
                coordinates = location['coordinates']
                longitude, latitude = coordinates[0], coordinates[1]
            else:
                longitude, latitude = 0, 0

            item = dict(
                id=str(locality.id),
                name=locality.name,
                name_en=locality.name_en,
                time_zone=locality.time_zone,
                cover=locality.cover,
                longitude=longitude,
                latitude=latitude,
                itinerary_covers=locality.itinerary_covers,
            )
    return api_ok(data=item)


@current_app.route('/vacation/admin/locality/add/', methods=['POST'])
@validate_form(form_class=LocalityInfoForm)
def add_locality():
    """
    ### 说明
    添加国家

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    name | Y | string |
    name_en | Y | string | 国家英文名字
    time_zone | Y | integer | 时区
    cover | Y | string | 国家封面图片
    longitude | Y | float | 国家经度
    latitude | Y | float | 国家纬度
    itinerary_covers | Y | string | 国家行程封面

    #### 返回结果
    {
      "code": 0,
      "data": {}
    }
    """

    form = g.form
    obj = dict(
        name=form.name.data,
        name_en=form.name_en.data,
        time_zone=form.time_zone.data,
        cover=form.cover.data,
        location=(form.longitude.data, form.latitude.data),
        itinerary_covers=form.itinerary_covers.data,
    )
    try:
        Locality.objects.create(**obj)
        return api_ok()
    except:
        return api_error(49999)


@current_app.route('/vacation/admin/locality/edit/', methods=['POST'])
@validate_form(form_class=LocalityInfoForm)
def edit_locality():
    """
    ### 说明
    编辑国家

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    id | Y | string | 被编辑的国家的id
    name | Y | string |
    name_en | Y | string | 国家英文名字
    time_zone | Y | integer | 时区
    cover | Y | string | 国家封面图片
    longitude | Y | float | 国家经度
    latitude | Y | float | 国家纬度
    itinerary_covers | Y | string | 国家行程封面

    #### 返回结果
    {
      "code": 0,
      "data": {}
    }
    """

    form = g.form
    if request.form:
        getter = request.form.get
    else:
        getter = MultiDict(request.get_json(force=True)).get

    id = get_objectId(getter('id'))
    if not id:
        return api_error(49999, msg=u"请选择要编辑的国家")

    locality = Locality.objects.filter(id=id).first()
    if not locality:
        return api_error(49999, msg=u"找不到国家")

    locality.name = form.name.data
    locality.name_en = form.name_en.data
    locality.time_zone = form.time_zone.data
    locality.cover = form.cover.data
    locality.location = (form.longitude.data, form.latitude.data)
    locality.itinerary_covers = form.itinerary_covers.data
    locality.save()

    return api_ok()


@current_app.route('/vacation/admin/locality/publish/', methods=['POST'])
def publish_locality():
    """
    ### 说明
    发布/取消发布 国家

    ### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    locality_id | Y | string | 被发布/取消发布的国家的id
    published ｜ Y ｜ boolean | 发布(True)或者取消发布(False)

    #### 返回结果
    {
      "code": 0,
      "data": {}
    }
    """

    if request.form:
        getter = request.form.get
    else:
        getter = MultiDict(request.get_json(force=True)).get

    locality_id = get_objectId(getter('locality_id'))
    if not locality_id:
        return api_error(49999, msg=u"请选择要修改发布状态的国家")

    published = getter('published')
    locality = Locality.objects.filter(id=locality_id).first()
    if not locality:
        return api_error(49999, msg=u"找不到国家")

    locality.published = published
    locality.save()

    return api_ok()


@current_app.route('/vacation/admin/locality/delete/', methods=['POST'])
def delete_locality():
    """
    ### 说明
    删除国家

    ### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    locality_id | Y | string | 被删除发布的国家的id

    #### 返回结果
    {
      "code": 0,
      "data": {}
    }
    """

    if request.form:
        getter = request.form.get
    else:
        getter = MultiDict(request.get_json(force=True)).get

    locality_id = get_objectId(getter('locality_id'))
    if not locality_id:
        return api_error(49999, msg=u"请选择要删除的国家")

    locality = Locality.objects.filter(id=locality_id).first()
    if not locality:
        return api_error(49999, msg=u"找不到国家")

    locality.delete()
    return api_ok()


@current_app.route('/vacation/admin/locality/order/', methods=['POST'])
def order_locality():
    """
    ### 说明
    国家排序

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    locality_ids | N | string | 国家id字符串

    #### 返回结果
    {
      "code": 0,
      "data": {}
    }
    """
    if request.form:
        getter = request.form.get
    else:
        getter = MultiDict(request.get_json(force=True)).get

    locality_ids = getter('locality_ids', '').split(',')
    if not all(map(lambda id: get_objectId(id), locality_ids)):
        return api_error(49999, msg=u"请选择正确的国家进行排序")

    ids = [get_objectId(e) for e in locality_ids]
    localities = Locality.objects.filter(id__in=ids)
    for i, locality_id in zip(xrange(len(locality_ids)), locality_ids):
        locality = localities.get(id=locality_id)
        locality.position = i
        locality.save()

    return api_ok()


@current_app.route('/vacation/admin/destination/list/', methods=['GET'])
def destination_list():
    """
    ### 说明
    获取指定国家的目的地（城市）列表

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    locality_id | N | string |

    #### 返回结果
    {
      "code": 0,
      "data": [
        {
          "id": "5609ff942e809f57ab2f8ab6",
          "name": "仙台",
          "published": false
        },
        {
          "id": "5609ff942e809f57ab2f8aac",
          "name": "京都",
          "published": true
        },
        ...
      ]
    }
    """

    getter = request.args.get

    items = []

    locality_id = get_objectId(getter('locality_id'))
    if locality_id:
        condition = Q(locality=locality_id, is_departured=False)
        destinations = paginate_queryset(
            request.args,
            Destination.objects.filter(condition)
        )
        for destination in destinations:
            items.append({
                'id': str(destination.id),
                'name': destination.name,
                'published': destination.published,
            })
    return api_ok(data=items)


@current_app.route('/vacation/admin/destination/info/', methods=['GET'])
def destination_info():
    """
    ### 说明
    获取目的地信息

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    destination_id | N | string |

    ### 请求参数
    {
      "code": 0,
      "data": {
        "images": "[\"http://photos.breadtrip.com/covers_2015_04_17_c44fca39370ac57b75bdd8ebe5e06bd9.jpg?imageView/2/w/960/\", \"http://photos.breadtrip.com/covers_2015_05_25_d70898f0520837ad038ee4f2f7a75fa6.jpg?imageView/2/w/960/\", \"http://photos.breadtrip.com/covers_2015_03_24_da2a0db356289c582d268cfc63b9e9ab.jpg?imageView/2/w/960/q/85\", \"http://photos.breadtrip.com/covers_2015_04_17_3f9b3a390b3200704aecfcb5504e67f2.jpg?imageView/2/w/960/\"]",
        "latitude": 0,
        "locality_id": "5609ff712e809f57ab1e8b16",
        "longitude": 0,
        "max_days": 2,
        "min_days": 1,
        "name": "洛桑",
        "periphery": "沃韦 蒙特勒",
        "tags": [
          "奥林匹克",
          "海滨度假",
          "休闲",
          "高等学府",
          "教堂建筑",
          "葡萄园风光"
        ]
      }
    }
    """
    item = {}
    getter = request.args.get

    id = get_objectId(getter('destination_id'))
    if id:
        destination = Destination.objects.filter(id=id).first()
        item = get_destination_info(destination)

    return api_ok(item)


@current_app.route('/vacation/admin/destination/add/', methods=['POST'])
@validate_form(form_class=DestinationInfoForm)
def add_destination():
    """
    ### 说明
    添加目的地（城市）

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    name | Y | string |
    name_en | Y | string | 城市英文名字
    cover | Y | string | 城市封面图片
    locality_name | Y | string | 被添加城市所属的国家
    longitude | Y | float | 城市经度
    latitude | Y | float | 城市纬度
    periphery | Y | string | 城市行程封面
    max_days ｜ Y | integer | 推荐最大天数
    min_days | Y | integer | 推荐最小天数

    #### 返回结果
    {
      "code": 0,
      "data": {}
    }
    """

    form = g.form
    if request.form:
        getter = request.form.get
    else:
        getter = MultiDict(request.get_json(force=True)).get

    locality_name = trim(getter('locality_name'))
    locailty = Locality.objects.filter(name=locality_name).first()
    if locailty is None:
        locailty = Locality.objects.create(**dict(name=locality_name))

    destination_obj = dict(
        name=form.name.data,
        location=(form.longitude.data, form.latitude.data),
        locality=locailty.id,
    )
    destination = Destination.objects.create(**destination_obj)

    if destination:
        tag_condition = Q(name__in=form.tags.data.split(','))
        tags = [e for e in Tag.objects.filter(tag_condition)]
        obj = dict(
            destination=destination.id,
            tags=tags,
            max_days=form.max_days.data,
            min_days=form.min_days.data,
            periphery=form.periphery.data,
        )
        try:
            DestinationInfo.objects.create(**obj)
            return api_ok(data=dict(locality_id=str(locailty.id)))
        except Exception as e:
            print e
            return api_error(49999)
    else:
        return api_error(49999, msg=u"添加城市失败")


@current_app.route('/vacation/admin/destination/edit/', methods=['POST'])
@validate_form(form_class=DestinationInfoForm)
def edit_destination():
    """
    编辑目的地（城市）

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    id | Y | string | 被编辑城市的id
    name | Y | string | 城市名称
    cover | Y | string | 城市封面图片
    locality_name | Y | string | 被添加城市所属的国家
    longitude | Y | float | 城市经度
    latitude | Y | float | 城市纬度
    periphery | Y | string | 城市行程封面
    max_days ｜ Y | integer | 推荐最大天数
    min_days | Y | integer | 推荐最小天数

    ### 返回结果
    {
      "code": 0,
      "data": {}
    }
    """

    form = g.form
    if request.form:
        getter = request.form.get
    else:
        getter = MultiDict(request.get_json(force=True)).get

    id = get_objectId(getter('id'))
    if not id:
        return api_error(49999, msg=u"请选择要编辑的城市")

    destination = Destination.objects.filter(id=id).first()
    if not destination:
        return api_error(49999, msg=u"找不到城市")

    tag_condition = Q(name__in=form.tags.data.split(','))
    tags = Tag.objects.filter(tag_condition)

    destination.name = form.name.data
    destination.location = (form.longitude.data, form.latitude.data)
    destination.save()

    destination_condition = Q(destination=destination.id)
    destination_info = DestinationInfo.objects.filter(destination_condition).first()
    if destination_info:
        destination_info.max_days = form.max_days.data
        destination_info.min_days = form.min_days.data
        destination_info.tags = tags
        destination_info.save()

    item = get_destination_info(destination)
    return api_ok(item)


@current_app.route('/vacation/admin/destination/publish/', methods=['POST'])
def publish_destination():
    """
    ### 说明
    发布/取消发布 目的地（城市）

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    destination_id | Y | string | 被发布/取消发布的目的地的id
    published ｜ Y ｜ boolean | 发布(True)或者取消发布(False)

    #### 返回结果
    {
      "code": 0,
      "data": {}
    }
    """

    if request.form:
        getter = request.form.get
    else:
        getter = MultiDict(request.get_json(force=True)).get

    destination_id = get_objectId(getter('destination_id'))
    if not destination_id:
        return api_error(49999, msg=u"请选择要修改发布状态的城市")

    published = getter('published')
    destination = Destination.objects.filter(id=destination_id).first()
    if not destination:
        return api_error(49999, msg=u"找不到城市")

    destination.published = published
    destination.save()

    return api_ok(dict(locality_id=str(destination.locality.id)))


@current_app.route('/vacation/admin/destination/delete/', methods=['POST'])
def delete_destination():
    """
    ### 说明
    删除目的地（城市）

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    destination_id | Y | string | 被删除发布的目的地的id

    #### 返回结果
    {
      "code": 0,
      "data": {}
    }
    """

    if request.form:
        getter = request.form.get
    else:
        getter = MultiDict(request.get_json(force=True)).get

    destination_id = get_objectId(getter('destination_id'))
    if not destination_id:
        return api_error(49999, msg=u"请选择要删除的城市")

    destination = Destination.objects.filter(id=destination_id).first()
    if not destination:
        return api_error(49999, msg=u"找不到城市")

    destination.delete()
    return api_ok(dict(locality_id=str(destination.locality.id)))


@current_app.route('/vacation/admin/tag/list/', methods=['GET'])
def tag_list():
    """
    ### 说明
    获取目的地（城市）标签

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    destination_id | Y | string | 目的地的id

    ### 返回结果
    {
      "code": 0,
      "data": {
        "destination_tags": {
          "5609ff712e809f57ab1e89f1": "休闲",
          "5609ff712e809f57ab1e89f5": "莱蒙湖景",
          "5609ff712e809f57ab1e89f6": "传奇古堡",
          "5609ff712e809f57ab1e89f7": "音乐之都",
          "5609ff712e809f57ab1e89f8": "传统美食"
        },
        "tags": {
          "561cbd35db95e12e11ab4b30": "旅游",
          "561cc2efdb95e12e11ab4b31": "吃",
          "561cc331db95e12e11ab4b32": "喝",
          "561cd3c0db95e12e11ab4b33": "测试",
          "561cd61cdb95e12e11ab4b35": "你在世界的这一端",
          "561cd8bcdb95e12e11ab4b36": "吃喝",
          "561ce5bcdb95e12e11ab4b38": "全绽放",
          "561ce60ddb95e12e11ab4b39": "海滨",
          "561cf7f2db95e12e11ab4b3a": "乐",
          "561cfa86db95e12e11ab4b3b": "玩"
        }
      }
    }
    """

    getter = request.args.get

    search_tag = getter('name')
    if not search_tag:
        destination_id = get_objectId(getter('destination_id'))
        if not destination_id:
            return api_error(49999, msg=u"请选择城市")

        tags = Tag.objects.all().order_by('date_added').limit(10)

        condition = Q(destination=destination_id)
        destination_info = DestinationInfo.objects.filter(condition).first()
        if not destination_info:
            return api_error(49999, msg=u"找不到该城市信息")

        destination_tags = {str(e.id): e.name for e in destination_info.tags}
        data = dict(
            tags={str(e.id): e.name for e in tags},
            destination_tags=destination_tags
        )
    else:
        tags = Tag.objects.filter(name__contains=search_tag)
        data = dict(tags={str(e.id): e.name for e in tags})

    return api_ok(data)


@current_app.route('/vacation/admin/destination/tag/add/', methods=['POST'])
def add_destination_tag():
    """
    添加目的地（城市）标签

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    destination_id | Y | string | 目的地的id
    tag_name | Y | string | 标签名称

    ####  返回结果
    {
      "code": 0,
      "data": {}
    }
    """

    if request.form:
        getter = request.form.get
    else:
        getter = MultiDict(request.get_json(force=True)).get

    name = trim(getter('name', ''))
    if name:
        tag = Tag.objects(name=name).modify(upsert=True,
                                            new=True,
                                            set__name=name)

        destination_id = get_objectId(getter('destination_id'))
        if not destination_id:
            return api_error(49999, msg=u"请选择城市")

        condition = Q(destination=destination_id)
        DestinationInfo.objects.filter(condition).update_one(push__tags=tag)

    return api_ok(dict(tag_name=tag.name, tag_id=str(tag.id)))


@current_app.route('/vacation/admin/destination/tag/delete/', methods=['POST'])
def delete_destination_tag():
    """
    ### 说明
    删除目的地（城市）标签

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    destination_id | Y | string | 目的地的id
    tag_id | Y | string | 标签id

    ####  返回结果
    {
      "code": 0,
      "data": {}
    }
    """

    if request.form:
        getter = request.form.get
    else:
        getter = MultiDict(request.get_json(force=True)).get

    tag_id = get_objectId(getter('tag_id'))
    tag = Tag.objects.filter(id=tag_id).first()
    if not tag:
        return api_error(49999, msg=u"请选择要删除的标签")

    destination_id = get_objectId(getter('destination_id'))
    if not destination_id:
        return api_error(49999, msg=u"请选择城市")
    
    condition = Q(destination=destination_id)
    DestinationInfo.objects.filter(condition).update_one(pull__tags=tag)

    return api_ok()


@current_app.route('/vacation/admin/upload/image/', methods=['POST'])
def upload_image():
    """
    ### 说明
    上传图片

    #### 请求参数
    参数名 | 必选 | 类型及范围 | 说明
    ---- | ---- | ---- | ----
    image | Y | file | 上传图片


    ####  返回结果
    {
      "code": 0,
      "data": {
        "url": "http://breadtripimages.qiniudn.com/covers_2015_10_14_abcdd1c41c37d552642c095de3ea5d99.jpg?imageView/2/w/960/q/85"
      }
    }
    """

    upload_image_url = current_app.config.get('UPLOAD_IMAGE_URL')
    if not upload_image_url:
        return api_error(49999, msg=u"上传图片失败")

    image = request.files.get('image')

    if image and allowed_file(image.filename):
        ret, resp = btapi.upload_image(image.read())
        data = ret.get('data')
        if not ret.get('status'):
            if data and isinstance(data, dict):
                return api_ok(dict(url=data.get('url')))

        return api_error(49999, msg=ret.get('message', u"上传失败"))

    return api_error(49999, u"上传图片格式不对")
